/**
 * @file log_service.c
 * @brief 日志服务模块实现
 * 
 * 该模块实现UDP日志服务器，接收日志数据并写入文件。
 * 支持日志文件轮转和错误恢复。
 * 
 * @author 伞控无人机项目组
 * @date 2024
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.h>
#include "log_service.h"
#include "log_utils.h"
#include <sys/types.h>
#include <dirent.h>
#include <sys/statvfs.h>
#include <signal.h> // For sig_atomic_t

// 日志文件配置 - 统一使用单一路径
#define LOG_BASE_DIR "/root/user_data/sysl_log"  // 日志根目录（绝对路径）
#define LOG_LAST_RECORD "last_record"            // 活跃日志目录
#define LOG_LAST_RECORD_FILE "last_record_file"  // 活跃日志文件名
#define LOG_TIME_MARK_FILE "start_time.mark"     // 时间标记文件
#define MIN_VALID_YEAR 2023                      // 对时有效年份
#define STARTUP_FREE_SPACE_BYTES (500*1024*1024) // 启动时需要500MB磁盘空间
#define RUNTIME_MIN_FREE_SPACE_BYTES (200*1024*1024) // 运行时最低200MB
#define CLEANUP_TARGET_FREE_SPACE_BYTES (200*1024*1024) // 清理目标200MB
#define LOG_CHECK_INTERVAL_SEC 1                 // 对时检测周期
#define LOG_CLEAN_INTERVAL_SEC 300               // 空间清理周期（5分钟）
#define LOG_FILE_MAX_SIZE (10 * 1024 * 1024)     // 10MB轮转阈值
#define LOG_FILE_MAX_COUNT 10                    // 最大保留文件数
#define TIME_JUMP_THRESHOLD_SEC 1800             // 时间跳变检测阈值（30分钟，支持多次GPS同步）
#define MIN_KEEP_DIRS 3                          // 至少保留的目录数

// 写入策略优化
#define LOG_WRITE_BUFFER_SIZE (32 * 1024)        // 32KB写入缓冲区
#define LOG_FSYNC_INTERVAL 500                   // 每500条日志fsync一次
#define LOG_EMERGENCY_FSYNC_INTERVAL 50          // 紧急情况下每50条fsync一次

// 时间同步状态枚举已在头文件 log_service.h 中定义

// 全局变量
static volatile sig_atomic_t g_thread_running = 1;  // 线程运行标志（改进可见性）
static int g_server_socket = -1;                    // UDP服务器socket
static FILE *g_log_file = NULL;                     // 日志文件句柄
static pthread_mutex_t g_file_mutex = PTHREAD_MUTEX_INITIALIZER;
static char g_log_dir[256] = {0};                  // 当前日志目录
static char g_log_file_path[512] = {0};            // 当前日志文件
static char g_time_mark_path[512] = {0};           // 当前时间标记文件
static uint64_t g_current_log_size = 0;            // 当前日志文件大小
static time_t g_last_system_time = 0;              // 上次系统时间

// 新增时间管理变量
static time_t g_system_start_time = 0;             // 系统启动时间（立即记录）
static time_t g_final_start_time = 0;              // 最终确定的启动时间
static char g_task_directory[256] = {0};           // 任务目录名
static int g_directory_renamed = 0;                // 目录是否已重命名标志
static time_sync_state_t g_time_sync_state = TIME_SYNC_INIT; // 时间同步状态
static time_t g_time_sync_history[10];             // 记录最近10次时间变化
static int g_history_index = 0;                    // 历史记录索引
static int g_log_write_count = 0;                  // 写入计数器
static int g_gps_sync_count = 0;                   // GPS同步次数统计

// 内部函数声明
static int init_log_server(void);
static void rotate_log_file(void);
static void cleanup_log_server(void);
static int check_startup_disk_space(void);
static void record_startup_time(void);
static int detect_time_sync_enhanced(void);
static void rename_task_directory_to_real_time(time_t real_start_time);
static void recreate_task_directory_with_time(time_t new_start_time);
static void create_task_directory_with_time(time_t start_time);
static void add_file_header(void);
static void add_file_footer(void);
static int write_log_to_file(const char *data, size_t len);
static void record_time_change(time_t old_time, time_t new_time, const char *reason);
static void cleanup_disk_space_runtime(void);

// 工具函数：获取当前系统时间字符串
static void get_time_string(time_t t, char *buf, size_t buflen) {
    struct tm tm_info;
    localtime_r(&t, &tm_info);
    strftime(buf, buflen, "%Y%m%d_%H%M%S", &tm_info);
}

// 工具函数：判断系统时间是否有效（对时）
static int is_time_valid(time_t t) {
    struct tm tm_info;
    localtime_r(&t, &tm_info);
    return (tm_info.tm_year + 1900) >= MIN_VALID_YEAR;
}

// 工具函数：写入时间标记文件
static void write_time_mark(const char *path, time_t t) {
    FILE *fp = fopen(path, "w");
    if (fp) {
        fprintf(fp, "%ld\n", (long)t);
        char buf[64];
        get_time_string(t, buf, sizeof(buf));
        fprintf(fp, "%s\n", buf);
        fclose(fp);
    }
}

// 工具函数：读取时间标记文件
static time_t read_time_mark(const char *path) {
    FILE *fp = fopen(path, "r");
    if (!fp) return 0;
    long t = 0;
    fscanf(fp, "%ld", &t);
    fclose(fp);
    return (time_t)t;
}

// 工具函数：递归删除目录
static void remove_dir_recursive(const char *path) {
    DIR *d = opendir(path);
    if (!d) return;
    struct dirent *entry;
    char buf[512];
    while ((entry = readdir(d)) != NULL) {
        if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
        snprintf(buf, sizeof(buf), "%s/%s", path, entry->d_name);
        struct stat st;
        if (!stat(buf, &st)) {
            if (S_ISDIR(st.st_mode)) remove_dir_recursive(buf);
            else unlink(buf);
        }
    }
    closedir(d);
    rmdir(path);
}

// 工具函数：磁盘空间检查
static uint64_t get_free_space(const char *path) {
    struct statvfs vfs;
    if (statvfs(path, &vfs) == 0) {
        return (uint64_t)vfs.f_bsize * vfs.f_bavail;
    }
    return 0;
}

// 工具函数：重命名目录和文件
static void rename_log_dir_and_file(const char *old_dir, const char *new_dir) {
    rename(old_dir, new_dir);
    // 可选：如需重命名内部日志文件，可遍历重命名
}

// 工具函数：创建目录（替换system调用）
static int create_directory_recursive(const char *path) {
    char tmp[256];
    char *p = NULL;
    size_t len;
    
    snprintf(tmp, sizeof(tmp), "%s", path);
    len = strlen(tmp);
    if (tmp[len - 1] == '/') tmp[len - 1] = 0;
    
    for (p = tmp + 1; *p; p++) {
        if (*p == '/') {
            *p = 0;
            if (mkdir(tmp, 0755) != 0 && errno != EEXIST) {
                return -1;
            }
            *p = '/';
        }
    }
    if (mkdir(tmp, 0755) != 0 && errno != EEXIST) {
        return -1;
    }
    return 0;
}

// 新增：启动时磁盘空间检查
static int check_startup_disk_space(void) {
    // 确保日志根目录存在
    if (create_directory_recursive(LOG_BASE_DIR) != 0) {
        LOG_ERROR(LOG_TO_CONSOLE_ONLY, LOG_MODULE_LOGSVC, "创建日志根目录失败: %s", LOG_BASE_DIR);
        return -1; // 目录都无法创建，无法继续
    }

    // 尝试获取LOG_BASE_DIR空间，失败则回退到根路径
    uint64_t free_space = get_free_space(LOG_BASE_DIR);
    if (free_space == 0) {
        free_space = get_free_space("/");
    }

    if (free_space < STARTUP_FREE_SPACE_BYTES) {
        // 仅告警，不退出，避免开发环境/设备空间较小时完全禁用日志
        LOG_WARN(LOG_TO_CONSOLE_ONLY, LOG_MODULE_LOGSVC,
                 "磁盘空间不足(需%dMB, 有%dMB)，继续运行，日志可能受限", 
                 STARTUP_FREE_SPACE_BYTES / (1024*1024),
                 free_space / (1024*1024));
        return 0;
    }
    
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
            "磁盘空间检查通过，可用空间: %d MB", 
             free_space / (1024*1024));
    return 0;
}

// 新增：记录启动时间
static void record_startup_time(void) {
    g_system_start_time = time(NULL);
    g_last_system_time = g_system_start_time;
    g_final_start_time = g_system_start_time;  // 默认使用系统时间
    g_time_sync_state = TIME_SYNC_WAITING;     // 设置为等待GPS授时状态
    
    // 立即创建任务目录（使用系统时间）
    create_task_directory_with_time(g_system_start_time);
    
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
            "系统启动，启动时间: %ld (系统时间)", g_system_start_time);
}

// 新增：创建任务目录
static void create_task_directory_with_time(time_t start_time) {
    char time_str[64];
    get_time_string(start_time, time_str, sizeof(time_str));
    
    snprintf(g_task_directory, sizeof(g_task_directory), 
             "%s/%s", LOG_BASE_DIR, time_str);
    
    create_directory_recursive(g_task_directory);
    
    // 更新日志文件路径
    snprintf(g_log_file_path, sizeof(g_log_file_path), 
             "%s/task_log.txt", g_task_directory);
    
    // 创建时间标记文件
    char mark_path[512];
    snprintf(mark_path, sizeof(mark_path), "%s/%s", g_task_directory, LOG_TIME_MARK_FILE);
    write_time_mark(mark_path, start_time);
    
    // 更新全局变量
    strcpy(g_log_dir, g_task_directory);
    snprintf(g_time_mark_path, sizeof(g_time_mark_path), "%s/%s", g_task_directory, LOG_TIME_MARK_FILE);
}

// 新增：重命名目录为推断的真实时间
static void rename_task_directory_to_real_time(time_t real_start_time) {
    char real_time_str[64];
    get_time_string(real_start_time, real_time_str, sizeof(real_time_str));
    
    char new_dir[256];
    snprintf(new_dir, sizeof(new_dir), "%s/%s", LOG_BASE_DIR, real_time_str);
    
    if (strcmp(g_task_directory, new_dir) != 0) {
        if (rename(g_task_directory, new_dir) == 0) {
            strcpy(g_task_directory, new_dir);
            strcpy(g_log_dir, new_dir);
            snprintf(g_log_file_path, sizeof(g_log_file_path), 
                     "%s/task_log.txt", g_task_directory);
            snprintf(g_time_mark_path, sizeof(g_time_mark_path), "%s/%s", g_task_directory, LOG_TIME_MARK_FILE);
            
            LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
                    "任务目录重命名为推断时间: %s", real_time_str);
        }
    }
}

// 新增：重新创建任务目录（时间重置情况）
static void recreate_task_directory_with_time(time_t new_start_time) {
    // 关闭当前日志文件
    if (g_log_file) {
        add_file_footer();
        fclose(g_log_file);
        g_log_file = NULL;
    }
    
    // 创建新的任务目录
    create_task_directory_with_time(new_start_time);
    
    // 重新打开日志文件
    g_log_file = fopen(g_log_file_path, "a");
    if (g_log_file) {
        add_file_header();
        LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
                "重新创建任务目录，新启动时间: %ld", new_start_time);
    }
}

// 新增：添加文件头标记
static void add_file_header(void) {
    if (g_log_file) {
        time_t now = time(NULL);
        fprintf(g_log_file, "=== 任务开始时间: %ld ===\n", now);
        fflush(g_log_file);
    }
}

// 新增：添加文件尾标记
static void add_file_footer(void) {
    if (g_log_file) {
        time_t now = time(NULL);
        fprintf(g_log_file, "=== 任务结束时间: %ld ===\n", now);
        fflush(g_log_file);
        fsync(fileno(g_log_file));
    }
}

// 新增：记录时间变化历史
static void record_time_change(time_t old_time, time_t new_time, const char *reason) {
    g_time_sync_history[g_history_index] = new_time;
    g_history_index = (g_history_index + 1) % 10;
    
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
            "时间变化记录: %ld -> %ld, 原因: %s", old_time, new_time, reason);
}

// 新增：智能时间跳变检测（增强版）
static int detect_time_sync_enhanced(void) {
    time_t now = time(NULL);
    long time_diff = (long)(now - g_last_system_time);
    
    // 检测系统时间是否有效
    if (!is_time_valid(now)) {
        g_last_system_time = now;
        return 0;
    }
    
    // 检测时间跳变（30分钟阈值，支持多次GPS同步）
    if (labs(time_diff) > TIME_JUMP_THRESHOLD_SEC) {
        char reason[128];
        
        if (time_diff > 0) {
            // 时间向前跳变（GPS授时特征）
            snprintf(reason, sizeof(reason), "GPS授时向前跳变%ld秒", time_diff);
            
            // 增加GPS同步次数统计
            g_gps_sync_count++;
            
            if (g_time_sync_state == TIME_SYNC_WAITING) {
                g_time_sync_state = TIME_SYNC_DETECTED;
                
                // 推断系统启动时的真实时间
                time_t real_start_time = g_system_start_time + time_diff;
                
                if (is_time_valid(real_start_time)) {
                    g_final_start_time = real_start_time;
                    
                    // 重命名目录
                    if (!g_directory_renamed) {
                        rename_task_directory_to_real_time(real_start_time);
                        g_directory_renamed = 1;
                    }
                    
                    LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
                            "首次GPS授时检测成功，状态: %d -> %d，同步次数: %d", 
                            TIME_SYNC_WAITING, TIME_SYNC_DETECTED, g_gps_sync_count);
                }
            } else {
                // 后续的GPS同步
                LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
                        "检测到第%d次GPS同步，时间跳变: %ld秒，当前时间: %ld", 
                        g_gps_sync_count, time_diff, now);
            }
        } else {
            // 时间向后跳变
            snprintf(reason, sizeof(reason), "系统时间重置向后跳变%ld秒", labs(time_diff));
            
            // 重新计算启动时间
            time_t old_start_time = g_system_start_time;
            g_system_start_time = now;
            g_final_start_time = now;
            
            // 重新创建任务目录
            if (!g_directory_renamed) {
                recreate_task_directory_with_time(now);
            }
            
            LOG_WARN(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
                    "系统时间重置，启动时间: %ld -> %d", 
                    old_start_time, now);
        }
        
        // 记录时间变化历史
        record_time_change(g_last_system_time, now, reason);
        g_last_system_time = now;
        return 1;
    }
    
    g_last_system_time = now;
    return 0;
}

// 新增：运行时磁盘空间清理
static void cleanup_disk_space_runtime(void) {
    uint64_t free_space = get_free_space(LOG_BASE_DIR);
    
    if (free_space >= RUNTIME_MIN_FREE_SPACE_BYTES) {
        return;  // 空间充足，无需清理
    }
    
    LOG_WARN(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
             "磁盘空间不足，开始清理，当前可用: %d MB", 
             free_space / (1024*1024));
    
    // 收集所有任务目录（排除当前活跃目录）
    DIR *d = opendir(LOG_BASE_DIR);
    if (!d) return;
    
    struct task_dir_info {
        char name[256];
        time_t mtime;
        int is_current;
    } dirs[100];  // 最多100个目录
    int dir_count = 0;
    struct dirent *entry;
    
    while ((entry = readdir(d)) != NULL && dir_count < 100) {
        if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
        
        char path[512];
        snprintf(path, sizeof(path), "%s/%s", LOG_BASE_DIR, entry->d_name);
        struct stat st;
        
        if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) {
            strncpy(dirs[dir_count].name, entry->d_name, sizeof(dirs[dir_count].name) - 1);
            dirs[dir_count].mtime = st.st_mtime;
            dirs[dir_count].is_current = (strcmp(entry->d_name, 
                strrchr(g_task_directory, '/') ? strrchr(g_task_directory, '/') + 1 : g_task_directory) == 0) ? 1 : 0;
            dir_count++;
        }
    }
    closedir(d);
    
    // 按修改时间排序（最旧在前）
    for (int i = 0; i < dir_count - 1; i++) {
        for (int j = i + 1; j < dir_count; j++) {
            if (dirs[i].mtime > dirs[j].mtime) {
                struct task_dir_info temp = dirs[i];
                dirs[i] = dirs[j];
                dirs[j] = temp;
            }
        }
    }
    
    // 从最旧开始删除，直到达到目标空间
    int deleted_count = 0;
    for (int i = 0; i < dir_count; i++) {
        if (dirs[i].is_current) continue;  // 跳过当前任务目录
        
        char path[512];
        snprintf(path, sizeof(path), "%s/%s", LOG_BASE_DIR, dirs[i].name);
        
        remove_dir_recursive(path);
        deleted_count++;
        
        LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
                "清理旧任务目录: %s", dirs[i].name);
        
        // 检查是否达到目标空间
        free_space = get_free_space(LOG_BASE_DIR);
        if (free_space >= CLEANUP_TARGET_FREE_SPACE_BYTES) {
            break;
        }
    }
    
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
            "空间清理完成，删除 %d 个目录，当前可用空间: %d MB", 
             deleted_count, free_space / (1024*1024));
}

// 新增：优化写入函数
static int write_log_to_file(const char *data, size_t len) {
    pthread_mutex_lock(&g_file_mutex);
    
    if (g_log_file != NULL) {
        // 直接写入文件（减少缓冲区复杂度）
        size_t written = fwrite(data, 1, len, g_log_file);
        if (written == len) {
            g_current_log_size += len;
            g_log_write_count++;
            
            // 检查是否需要轮转日志文件
            if (g_current_log_size >= LOG_FILE_MAX_SIZE) {
                rotate_log_file();
            }
            
            // 定期fsync
            if (g_log_write_count % LOG_FSYNC_INTERVAL == 0) {
                fflush(g_log_file);
                fsync(fileno(g_log_file));
            }
            
            // 紧急fsync
            if (g_log_write_count % LOG_EMERGENCY_FSYNC_INTERVAL == 0) {
                fflush(g_log_file);
                fsync(fileno(g_log_file));
            }
        }
    }
    
    pthread_mutex_unlock(&g_file_mutex);
    return 0;
}

// 启动时处理遗留 last_record 目录
__attribute__((unused))
static void process_old_last_record(void) {
    char old_dir[256];
    snprintf(old_dir, sizeof(old_dir), "%s/%s", LOG_BASE_DIR, LOG_LAST_RECORD);
    
    // 检查是否存在遗留目录
    if (access(old_dir, F_OK) == 0) {
        char mark_path[512];
        snprintf(mark_path, sizeof(mark_path), "%s/%s", old_dir, LOG_TIME_MARK_FILE);
        
        // 读取时间标记
        time_t t = read_time_mark(mark_path);
        if (t > 0 && is_time_valid(t)) {
            // 使用推断的启动时间重命名
            char time_str[64];
            get_time_string(t, time_str, sizeof(time_str));
            
            char new_dir[256];
            snprintf(new_dir, sizeof(new_dir), "%s/%s", LOG_BASE_DIR, time_str);
            
            // 重命名目录
            if (rename(old_dir, new_dir) == 0) {
                LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
                        "重命名遗留日志目录: %s -> %s", old_dir, new_dir);
            }
        }
    }
}

// 创建新的 last_record 目录和文件（保留兼容性）
static void create_new_last_record(void) {
    // 这个函数在新的任务目录管理方式下不再需要
    // 保留是为了兼容性，实际不会被调用
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
            "create_new_last_record: 使用新的任务目录管理方式");
}

// 对时检测
__attribute__((unused))
static int detect_time_sync(void) {
    time_t now = time(NULL);
    long time_diff = (long)(now - g_last_system_time);
    
    // 检测无效年→有效年的对时
    if (!is_time_valid(g_last_system_time) && is_time_valid(now)) {
        g_last_system_time = now;
        return 1;
    }
    
    // 检测有效年内的显著时间跳变（对时修正），包含正负方向
    if (is_time_valid(g_last_system_time) && is_time_valid(now) && 
        labs(time_diff) > TIME_JUMP_THRESHOLD_SEC) {
        g_last_system_time = now;
        return 1;
    }
    
    g_last_system_time = now;
    return 0;
}

// 对时后处理（锁外日志）
__attribute__((unused))
static void handle_time_sync(void) {
    char time_str[64], new_dir[256];
    get_time_string(time(NULL), time_str, sizeof(time_str));
    snprintf(new_dir, sizeof(new_dir), "%s/%s", LOG_BASE_DIR, time_str);

    char old_dir_path[256];
    snprintf(old_dir_path, sizeof(old_dir_path), "%s", g_log_dir);
    
    pthread_mutex_lock(&g_file_mutex);
    if (g_log_file) { 
        fflush(g_log_file);
        fclose(g_log_file); 
        g_log_file = NULL; 
    }
    rename_log_dir_and_file(g_log_dir, new_dir);
    create_new_last_record();
    g_log_file = fopen(g_log_file_path, "a");
    g_current_log_size = 0;  // 重置文件大小计数
    pthread_mutex_unlock(&g_file_mutex);
    
    // 锁外记录日志（修正输出顺序：旧 -> 新）
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, "对时后重命名日志目录: %s -> %s", old_dir_path, new_dir);
}

// 空间清理（按时间排序，最旧优先）
__attribute__((unused))
static void clean_old_logs(void) {
    // 这个函数已被新的 cleanup_disk_space_runtime 替代
    // 保留是为了兼容性，实际不会被调用
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
            "clean_old_logs: 使用新的空间清理策略");
    
    // 调用新的清理函数
    cleanup_disk_space_runtime();
}

/**
 * @brief 获取GPS同步统计信息
 * 
 * @param sync_count 指向存储同步次数的指针
 * @param last_sync_time 指向存储最后同步时间的指针
 * @return 成功返回0，失败返回-1
 */
int get_gps_sync_statistics(int *sync_count, time_t *last_sync_time) {
    if (sync_count == NULL || last_sync_time == NULL) {
        return -1;
    }
    
    *sync_count = g_gps_sync_count;
    
    // 获取最后一次同步时间（从历史记录中获取）
    if (g_history_index > 0) {
        *last_sync_time = g_time_sync_history[(g_history_index - 1) % 10];
    } else if (g_history_index == 0 && g_gps_sync_count > 0) {
        *last_sync_time = g_time_sync_history[9];  // 最后一个位置
    } else {
        *last_sync_time = 0;  // 没有同步记录
    }
    
    return 0;
}

/**
 * @brief 获取当前时间同步状态
 * 
 * @return 时间同步状态枚举值
 */
time_sync_state_t get_time_sync_state(void) {
    return g_time_sync_state;
}

/**
 * @brief 日志服务主函数
 * 
 * @param arg 线程参数（未使用）
 * @return void* 返回值（未使用）
 */
void *log_service_function(void *arg) {
    (void)arg;
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, "日志服务启动");
    
    // 1. 启动时空间检查
    if (check_startup_disk_space() < 0) {
        LOG_ERROR(LOG_TO_FILE, LOG_MODULE_LOGSVC, "磁盘空间不足，服务退出");
        return NULL;
    }
    
    // 2. 记录启动时间并创建任务目录
    record_startup_time();
    
    // 3. 初始化日志服务器
    if (init_log_server() < 0) {
        LOG_ERROR(LOG_TO_FILE, LOG_MODULE_LOGSVC, "初始化日志服务失败，服务退出");
        return NULL;
    }
    
    // 4. 打开日志文件并添加文件头
    g_log_file = fopen(g_log_file_path, "a");
    if (g_log_file == NULL) {
        // 降级为控制台告警，不直接退出线程，让后续尝试仍可进行
        LOG_ERROR(LOG_TO_CONSOLE_ONLY, LOG_MODULE_LOGSVC, "无法打开日志文件: %s", g_log_file_path);
        // 继续运行主循环，但write_log_to_file()会因为g_log_file为NULL而跳过写入
        // 后续如目录修复或权限修复后，可考虑重试打开（需要进一步增强）
    } else {
        add_file_header();
    }
    
    // 5. 主循环
    time_t last_space_check = time(NULL);
    time_t last_time_check = time(NULL);
    char buffer[4096];
    struct sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);
    
    while (g_thread_running) {
        // 接收日志数据
        ssize_t recv_len = recvfrom(g_server_socket, buffer, sizeof(buffer) - 1, 0,
                                   (struct sockaddr*)&client_addr, &client_len);
        
        if (recv_len > 0) {
            buffer[recv_len] = '\0';
            write_log_to_file(buffer, recv_len);
        }
        
        // 高频时间检测（每秒检测）
        time_t now = time(NULL);
        if (now - last_time_check >= 1) {
            if (detect_time_sync_enhanced()) {
                // 时间同步检测到，记录详细信息
                LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
                        "时间同步状态: 启动时间=%ld, 当前时间=%ld, 运行时长=%ld秒", 
                        g_final_start_time, now, now - g_system_start_time);
            }
            last_time_check = now;
        }
        
        // 定期检查磁盘空间（每5分钟）
        if (now - last_space_check >= LOG_CLEAN_INTERVAL_SEC) {
            cleanup_disk_space_runtime();
            last_space_check = now;
        }
    }
    
    // 6. 优雅关闭
    add_file_footer();
    cleanup_log_server();
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, "日志服务退出");
    return NULL;
}

/**
 * @brief 停止日志服务运行
 */
void log_service_stop(void) {
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, "日志服务停止中");
    g_thread_running = 0;
}

/**
 * @brief 初始化日志服务器
 */
static int init_log_server(void) {
    struct sockaddr_in server_addr;
    
    // 创建UDP socket
    g_server_socket = socket(AF_INET, SOCK_DGRAM, 0);
    if (g_server_socket < 0) {
        LOG_ERROR(LOG_TO_FILE, LOG_MODULE_LOGSVC, "创建UDP socket失败: %s", strerror(errno));
        return -1;
    }
    
    // 设置缓冲区大小
    int buffer_size = LOG_UDP_BUFFER_SIZE;
    if (setsockopt(g_server_socket, SOL_SOCKET, SO_RCVBUF, &buffer_size, sizeof(buffer_size)) < 0) {
        LOG_WARN(LOG_TO_FILE, LOG_MODULE_LOGSVC, "设置接收缓冲区大小失败: %s", strerror(errno));
    }
    
    // 配置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(LOG_UDP_PORT);
    
    // 绑定socket
    if (bind(g_server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        LOG_ERROR(LOG_TO_FILE, LOG_MODULE_LOGSVC, "绑定UDP socket失败: %s", strerror(errno));
        close(g_server_socket);
        g_server_socket = -1;
        return -1;
    }
    
    return 0;
}

/**
 * @brief 轮转日志文件
 */
static void rotate_log_file(void) {
    if (!g_log_file) return;
    
    // 在新的任务目录管理方式下，不再进行文件轮转
    // 而是继续使用同一个文件，只记录轮转信息
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, 
            "日志文件大小达到 %d MB，继续追加（新策略：单文件管理）", 
            LOG_FILE_MAX_SIZE / (1024 * 1024));
    
    // 重置文件大小计数，继续使用当前文件
    g_current_log_size = 0;
}

/**
 * @brief 清理日志服务器资源
 */
static void cleanup_log_server(void) {
    if (g_server_socket >= 0) {
        close(g_server_socket);
        g_server_socket = -1;
    }
    
    pthread_mutex_lock(&g_file_mutex);
    if (g_log_file != NULL) {
        fflush(g_log_file);
        fclose(g_log_file);
        g_log_file = NULL;
    }
    pthread_mutex_unlock(&g_file_mutex);
}

// 新增：信号处理函数
static void signal_handler(int sig) {
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_LOGSVC, "接收到信号 %d，准备优雅关闭", sig);
    
    // 设置停止标志
    g_thread_running = 0;
    
    // 强制刷新缓冲区
    pthread_mutex_lock(&g_file_mutex);
    if (g_log_file != NULL) {
        // 添加文件尾标记
        add_file_footer();
        
        // 强制同步到磁盘
        fflush(g_log_file);
        fsync(fileno(g_log_file));
    }
    pthread_mutex_unlock(&g_file_mutex);
}

// 新增：注册信号处理
void register_signal_handlers(void) {
    signal(SIGTERM, signal_handler);
    signal(SIGINT, signal_handler);
} 